/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.text.Collator;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import net.worlds.object.Box;
import net.worlds.object.GameObject;
import net.worlds.object.Part;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2D;
import org.jbox2d.dynamics.contacts.ContactPoint;


public class Util {
    private static final Random rand = new Random();
    private static float[] angles;
    public static final Color transparent = new Color(0, 0, 0, 0);
    public static final FontRenderContext fontRendererContext = new FontRenderContext(null, false, false);
    private static DecimalFormat decimalFormat = new DecimalFormat("#.##");
    public static final ArrayList<Image> icons = new ArrayList<Image>(3);
    public static Color colorFromString(String s) throws WorldsException
    {
        try
        {
            String[] parts = s.split(",");
            return new Color(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
        }
        catch(Exception ex)
        {
            throw new WorldsException("Error parsing Color value");
        }
    }
    public static String colorToString(Color c)
    {
        return c.getRed()+","+c.getGreen()+","+c.getBlue();
    }
    public static Color randomColor()
    {
        int r = rand.nextInt(255);
        int g = rand.nextInt(255);
        int b = rand.nextInt(255);
        Color c = new Color(r, g, b);
        return c;
    }
    public static boolean isInteger(String s)
    {
        try
        {
            Integer.parseInt(s);
            return true;
        }
        catch(NumberFormatException ex)
        {
            return false;
        }
    }
    public static VolatileImage toVolatileImage(BufferedImage img)
    {
        VolatileImage vi = Util.getGraphicsConfiguration().createCompatibleVolatileImage(img.getWidth(), img.getHeight(), Transparency.TRANSLUCENT);
        Graphics2D g2 = vi.createGraphics();
        g2.setComposite(AlphaComposite.Src);
        g2.setColor(transparent);
        g2.fillRect(0, 0, vi.getWidth(), vi.getHeight());
        vi.getGraphics().drawImage(img, 0, 0, null);
        g2.dispose();
        return vi;
    }
    public static boolean isDouble(String s)
    {
        if(isInteger(s))
            return false;
        try
        {
            Double.parseDouble(s);
            return true;
        }
        catch(NumberFormatException ex2)
        {
            return false;
        }
    }
    public static boolean isColor(String s)
    {
        if(!s.contains(","))
            return false;
        String[] parts = s.split(",");
        if(parts.length != 3)
            return false;
        for(String p : parts)
        {
            if(!isDouble(p))
                return false;
            double d = Double.parseDouble(p);
            if((int) d < 0 || (int) d > 255)
                return false;
        }
        return true;
    }
    public static boolean isVec2D(String s)
    {
        if(!s.contains(","))
            return false;
        String[] parts = s.split(",");
        if(parts.length != 2)
            return false;
        for(String p : parts)
        {
            if(!isDouble(p) && !isInteger(p))
                return false;
        }
        return true;
    }
    public static void checkThread()
    {
        if(Thread.currentThread() != Main.mainThread)
            throw new RuntimeException("Wrong thread");
    }
    public static int parseUnsignedByte(byte b)
    {
        if(b < 0)
            return b + 256;
        else
            return b;
    }
    public static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuilder fileData = new StringBuilder(1000);
        BufferedReader reader = new BufferedReader(
                new FileReader(filePath));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            fileData.append(buf, 0, numRead);
        }
        reader.close();
        return fileData.toString();
    }
    public static String getTextFromResource(String re)
    {
        InputStream is = null;
        String script = "";
        try {
            URL url = Main.class.getResource(re);
            is = url.openConnection().getInputStream();
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String l = null;
            while ((l = r.readLine()) != null) {
                script = script + "\n" + l;
            }
        } catch (IOException ex) {
            Main.error(ex);
        } finally {
            try {
                is.close();
            } catch (IOException ex) {
            }
            return script;
        }
    }
    public static String getClipboardContents()
    {
        String result = "";
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        Transferable t = clipboard.getContents(null);
        if(t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor))
        {
            try {
                result = (String) t.getTransferData(DataFlavor.stringFlavor);
            } catch (UnsupportedFlavorException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
    public static String getExtension(String s) {
        String ext = null;
        int i = s.lastIndexOf('.');

        if (i > 0 &&  i < s.length() - 1) {
            ext = s.substring(i+1).toLowerCase();
        }
        return ext;
    }
    public static String httpGet(String address)
    {
        try {
            URL url = new URL(address);
            URLConnection con = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String result = "";
            String line;
            while((line = in.readLine()) != null)
                result += line + "\n";
            return result;
        } catch (Exception ex) {
            throw new RuntimeException("httpGet failed: "+ex);
        }
    }
    public static float roundTo45(float a)
    {
        float neededDistance = 45f/2;
        for(float i : angles)
        {
            if(Math.abs(i - a) - 1 <= neededDistance)
                return i;
        }
        return a;
    }
    public static void sortArray(Collator collator, String[] strArray) {
        String tmp;
        if (strArray.length == 1) return;
        for (int i = 0; i < strArray.length; i++) {
            for (int j = i + 1; j < strArray.length; j++) {
                if(strArray[i] != null && strArray[j] != null &&  collator.compare(strArray[i], strArray[j] ) > 0 ) {
                    tmp = strArray[i];
                    strArray[i] = strArray[j];
                    strArray[j] = tmp;
                }
            }
        }
    }
    public static boolean isPersistable(String type)
    {
        return !((type.equals("Camera") && !Main.isServer()) || (type.equals("Player") && !Main.isServer()) || type.equals("NetworkServer") || type.equals("NetworkClient") || type.equals("AssetService"));
    }
    public static boolean isLocal(String type)
    {
        return type.equals("NetworkClient") || type.equals("Connection") || type.equals("NetworkServer");
    }
    public static GraphicsConfiguration getGraphicsConfiguration()
    {
        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        return gc;
    }
    public static GraphicsDevice getGraphicsDevice()
    {
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        return gd;
    }
    public static boolean shouldStep(ContactPoint point, Part character, Box other) throws WorldsException
    {
        final Vec2D highest = new Vec2D(((PolygonShape)other.getShape()).getHighestPoint(point.position.x, 0.25f));
        final Vec2D size = character.getVec2DProp("Size");
        return highest.y > character.getPosition().y - size.y/2 && highest.y < character.getPosition().y - size.y/2 + 2.5 && Math.abs(character.getVelocity().x) > 0.3;
    }
    public static void performRequestWithCallback(final Runnable request, final Runnable callback)
    {
        Runnable r = new Runnable()
        {
            public void run() {
                try {
                    request.run();
                    Main.runInMainThread(callback);
                }
                catch(Exception ex)
                {
                    System.err.println(ex.getMessage());
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
    public static String base64Decode(String b64)
    {
        try {
            sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
            byte[] bytes = dec.decodeBuffer(new ByteArrayInputStream(b64.getBytes()));
            return new String(bytes);
        } catch (IOException ex) {
            throw new RuntimeException("Invalid Base64 data");
        }
    }
    public static List<GameObject> copyList(List<GameObject> a)
    {
        List<GameObject> result = new ArrayList<GameObject>(a);
        return result;
    }
    public static double roundTwoDecimals(double n)
    {
        try {
        return Double.valueOf(decimalFormat.format(n));
        }
        catch(NumberFormatException e)
        {
            return 0;
        }
    }   
    public static void wikiLookup(String object)
    {
       if(Desktop.isDesktopSupported())
                try {
                    Desktop.getDesktop().browse(URI.create("http://2dworlds.org/wiki/"+object));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
    }
    static {
        angles = new float[720/45];
        for(int i = 0; i < 720; i += 45)
        {
            angles[i/45] = i - 360;
        }
        icons.add(new ImageIcon(Util.class.getResource("/icon.png")).getImage());
        icons.add(new ImageIcon(Util.class.getResource("/icon32.png")).getImage());
        icons.add(new ImageIcon(Util.class.getResource("/icon64.png")).getImage());
    }
}
